package Queues;

public class ObjectFIFO implements java.io.Serializable{  
	 
         private Object[] queue;  
 
         private int capacity;  
 
         private int size;  
 
         private int head;  
 
         private int tail;  
 
 
         public ObjectFIFO(int cap) {  
 
             capacity = ( cap > 0 ) ? cap : 1; // at least 1  
 
           queue = new Object[capacity];  
 
           head = 0;  
 
           tail = 0;  
 
           size = 0;  
 
       }  
 
     
 
       public int getCapacity() {  
 
           return capacity;  
 
       }  
 
     
 
       public synchronized int getSize() {  
 
           return size;  
 
       }  
 
     
 
       public synchronized boolean isEmpty() {  
 
           return ( size == 0 );  
 
       }  
 
     
 
       public synchronized boolean isFull() {  
 
           return ( size == capacity );  
 
       }  
 
     
 
       public synchronized void add(Object obj)   
 
             throws InterruptedException {  
 
     
 
           waitWhileFull();  
 
     
 
           queue[head] = obj;  
 
           head = ( head + 1 ) % capacity;  
 
           size++;  
 
     
 
           notifyAll(); // let any waiting threads know about change  
 
       }  
 
     
 
       public synchronized void addEach(Object[] list)   
 
               throws InterruptedException {  
 
     
 
           //  
 
           // You might want to code a more efficient   
 
           // implementation here ... (see ByteFIFO.java)  
 
           //  
 
     
 
           for ( int i = 0; i < list.length; i++ ) {  
 
               add(list[i]);  
 
           }  
 
       }  
 
     
 
       public synchronized Object remove()   
 
               throws InterruptedException {  
 
     
 
           waitWhileEmpty();  
 
     
 
           Object obj = queue[tail];  
 
     
 
           // don�t block GC by keeping unnecessary reference  
 
           queue[tail] = null;   
 
     
 
           tail = ( tail + 1 ) % capacity;  
 
           size--;  
 
     
 
           notifyAll(); // let any waiting threads know about change  
 
     
 
           return obj;  
 
       }  
 
     
 
       public synchronized Object[] removeAll()   
 
               throws InterruptedException {  
 
     
 
           //  
 
           // You might want to code a more efficient   
 
           // implementation here ... (see ByteFIFO.java)  
 
           //  
 
     
 
           Object[] list = new Object[size]; // use the current size  
 
     
 
           for ( int i = 0; i < list.length; i++ ) {  
 
               list[i] = remove();  
 
           }  
 
     
 
           // if FIFO was empty, a zero-length array is returned  
 
           return list;   
 
       }  
 
     
 
       public synchronized Object[] removeAtLeastOne()   
 
               throws InterruptedException {  
 
     
 
           waitWhileEmpty(); // wait for at least one to be in FIFO  
 
           return removeAll();  
 
       }  
 
     
   
      public synchronized boolean waitUntilEmpty(long msTimeout)   
 
               throws InterruptedException {  
 
     
 
           if ( msTimeout == 0L ) {  
 
               waitUntilEmpty();  // use other method  
 
               return true;  
 
           }  
 
     
 
           // wait only for the specified amount of time  
 
           long endTime = System.currentTimeMillis() + msTimeout;  
 
           long msRemaining = msTimeout;  
 
     
 
           while ( !isEmpty() && ( msRemaining > 0L ) ) {  
 
               wait(msRemaining);  
 
               msRemaining = endTime - System.currentTimeMillis();  
 
           }  
 
     
 
           // May have timed out, or may have met condition,   
 
           // calc return value.  
 
           return isEmpty();  
 
       }  
 
     
 
       public synchronized void waitUntilEmpty()   
 
               throws InterruptedException {  
 
     
 
           while ( !isEmpty() ) {  
 
               wait();  
 
           }  
 
       }  
 
     
 
       public synchronized void waitWhileEmpty()   
 
               throws InterruptedException {  
 
     
 
           while ( isEmpty() ) {  
 
               wait();  
 
           }  
 
       }  
 
     
 
       public synchronized void waitUntilFull()   
 
               throws InterruptedException {  
 
     
 
           while ( !isFull() ) {  
 
               wait();  
 
           }  
 
       }  
 
     
 
       public synchronized void waitWhileFull()   
 
               throws InterruptedException {  
 
     
 
           while ( isFull() ) {  
 
               wait();  
 
           }  
 
       }  
 
   } 
 
